/**************************************************************************
 * @file PD_PHY.c
 * @author 黑马小乌龟 (532352406@qq.com)
 * @brief 
 * @version 0.1
 * @date 2025-08-20
 * 
 * @copyright Copyright (c) 2025
 * 
 *************************************************************************/
#include "PD_PHY.H"
#include <stdio.h>
#include "DEBUG.H"
#include "system.h"

_PD_PHY_STAT pd_phy_state = {0};
_Union_Header xdata *Union_Header;    
_Union_SrcCap xdata *Union_SrcCap;    
_Union_VDM_Hdr xdata *Union_VDM_Hdr;  

xdata UINT8 pd_rx_buf[30];
xdata UINT8 pd_tx_buf[30];
UINT8X PD_Source[30];
UINT8X CCSel = 0;
UINT8X MsgID = 0;
UINT8X Send_Count = 0;
UINT8X NDORcv;
UINT8X PPS_Flag = 0;

// extern UINT8X Temp_PDO;
// extern UINT8X PD_Request_Gears;

void pd_phy_init(void) {
    UINT8 dat;
    P1_MOD_OC &= ~(bCC1 | bCC2);
    P1_DIR_PU &= ~(bCC1 | bCC2);

    CC1_CTRL &= ~bCC_CE;
    CC1_CTRL |= bCC_CVS1;
    CC1_CTRL &= ~bCC_CMPO;
    CC1_CTRL |= (bCC_CE | bCC_PD);  // 

    CC2_CTRL &= ~bCC_CE;
    CC2_CTRL |= bCC_CVS1;
    CC2_CTRL &= ~bCC_CMPO;
    CC2_CTRL |= (bCC_CE | bCC_PD);  // 

    ADC_CTRL |= bADC_EN;                   
    ADC_CTRL &= ~(bADC_CLK0 | bADC_CLK1);  
    dat = ADC_DAT;                         
    ADC_CTRL |= bADC_IF;                   
}

UINT8 Check_Dev_Remove(void) {
    ADC_CHAN = (ADC_CHAN & ~0x0F) | (CCSel - 1);
    ADC_CTRL |= bADC_START;
    while ((ADC_CTRL & bADC_IF) == 0); 
    ADC_CTRL |= bADC_IF;               
    if (ADC_DAT < DufaultPowerMin) {
        TR0 = 0;
        ET0 = 0;
        // PD_Request_Gears = 1;
        // Temp_PDO = 1;
        pd_phy_state.SendingRequest = 0;
        pd_phy_state.SendingGoodCRC = 0;
        pd_phy_state.WaitingGoodCRC = 0;
        pd_phy_init();
        return 1;
    }

    return 0;
}


UINT8 Check_CC_Connect(void) {
    if ((CC1_CTRL & bCC_CMPO) == 1) {
        CCSel = 1;
        CC1_CTRL &= ~(bCC_CVS1 | bCC_CVS0);
        UPD_CTRL &= ~(bPD_CC_SEL);
        my_printf("CC1 Connect! \n", 0);
        return 1;
    } else if ((CC2_CTRL & bCC_CMPO) == 1) {
        CCSel = 2;
        CC2_CTRL &= ~(bCC_CVS1 | bCC_CVS0);
        UPD_CTRL |= bPD_CC_SEL;
        my_printf("CC2  Connect!\n", 0);
        return 1;
    }

    return 0;
}


void mTimer_x_SetData(UINT16 dat) {
    UINT16 tmp;
    TR0 = 0;
    tmp = 65536 - dat;  // 2000
    TL0 = tmp & 0xff;
    TH0 = (tmp >> 8) & 0xff;

    TR0 = 1;  
    ET0 = 1;  
}


void Timer0Init(void) {
    T2MOD &= ~bT0_CLK;              
    TMOD = ((TMOD & 0xf0) | 0x01);  
    TR0 = 0;                        
    ET0 = 0;                        
}

void pd_phy_isr_handle(void) interrupt INT_NO_USBPD using 1 {
    if (PIF_RX_RST) { 
        my_printf("RST\n", 0);
        pd_phy_h_reset();  
        pd_phy_rx_init();
    }
    if (PIF_RX_ACT) { 
        TR0 = 0;
        ET0 = 0;
        PIF_RX_ACT = 0;
        if ((UPD_INT_FG & MASK_PD_STAT) == PD_RX_SOP0) {  
            Union_Header = (_Union_Header *)pd_rx_buf;    
            if (pd_phy_state.WaitingGoodCRC) {            
                if (Union_Header->HeaderStruct.MsgType == GoodCRC) {
                    pd_phy_state.WaitingGoodCRC = 0;
                    if (pd_phy_state.SendingRequest == 1) {
                        pd_phy_state.SendingRequest = 0;
                    }
                    Send_Count = 0;
                    usr_pd_port_isr();
                }
            } else {
                switch (Union_Header->HeaderStruct.MsgType) {
                    case SourceCap:
                        NDORcv = Union_Header->HeaderStruct.NDO;
                        memcpy(PD_Source, pd_rx_buf, 30);
                        pd_phy_state.SendingRequest = 1;
                        break;
                    case Request:
                        break;
                    case Accept:
                        MsgID++;
                        break;
                    case Reject:
                        break;
                    case PS_RDY:
                        break;
                    case GetSrcCap:
                        MsgID++;
                        pd_phy_state.SendingSourceCap = 1;
                        break;
                    case GetSinkCap:
                        MsgID++;
                        pd_phy_state.SendingSinkCap = 1;
                        break;
                    case SourceCap_VDM:
                        break;
                    default:
                        break;
                }
                mDelayuS(25);
                pd_phy_state.SendingGoodCRC = 1;  
                pd_phy_send_good_crc();           
            }
        } else
            pd_phy_rx_init();
    }
    if (PIF_TX_END) {
        PIF_TX_END = 0;
        if (CCSel == 1) { 
            CC1_CTRL &= ~bCC_LVO;
        } else if (CCSel == 2) {
            CC2_CTRL &= ~bCC_LVO;
        }
        if (pd_phy_state.SendingGoodCRC == 1) {
            pd_phy_state.SendingGoodCRC = 0;
            usr_pd_port_isr();  
        } else {            
            pd_phy_state.WaitingGoodCRC = 1;
            mTimer_x_SetData(10000);  // 5ms
            pd_phy_rx_init();
        }
    }
}
#if 0
void pd_phy_send_req_capacity(void) {
    UINT16 Volt_Value;
    UINT8 temp = 0xff;  // 
    UINT8 i;
    UINT16 Temp;
    UINT16 Data_H8;
    UINT16 Cur_Temp = 0;
    switch (Temp_PDO) {
        case 1:
            Volt_Value = 5000;
            my_printf("Request  5V \n", 0);
            break;
        case 2:
            Volt_Value = 9000;
            my_printf("Request  9V \n", 0);
            break;
        case 3:
            Volt_Value = 12000;
            my_printf("Request  12V \n", 0);
            break;
        case 4:
            Volt_Value = 15000;
            my_printf("Request  15V \n", 0);
            break;
        case 5:
            Volt_Value = 20000;
            my_printf("Request  20V \n", 0);
            break;
        default:
            Volt_Value = 5000;
            break;
    }
    
    for (i = 0; i < NDORcv; i++) {
        Union_SrcCap = (_Union_SrcCap *)&PD_Source[2 + (4 * i)];
        Data_H8 = (Union_SrcCap->SrcCapStruct.DataH8);
        if ((Data_H8 >> 6) == 3) {
            PPS_Flag = 1;
            my_printf("\r %d is PPS\n", (UINT16)(i + 1));
        } else {
            Temp = (PD_Source[3 + (i << 2)] >> 2) + ((PD_Source[4 + (i << 2)] & 0x0F) << 6);
            Temp *= 50;
            if (Temp <= Volt_Value) {
                if (Temp > Cur_Temp) {
                    Cur_Temp = Temp;
                    temp = i + 1;
                }
            }
        }
    }
    if (Temp_PDO != temp) {
        my_printf("No requested voltage! \n", 0);
        my_printf("Request adjacent voltage! \n", 0);
    }
    if (temp != 0xff) {
        UPD_T_SOP = UPD_SOP0;
        UPD_T_LEN = 6;
        pd_tx_buf[5] = ((temp << 4) | 0x02);
        pd_tx_buf[4] = ((PD_Source[3 + ((temp - 1) << 2)] & 0x03) << 2) | (PD_Source[2 + ((temp - 1) << 2)] >> 6) | (PD_Source[4 + ((temp - 1) << 2)] & 0xF0);
        pd_tx_buf[3] = (PD_Source[3 + ((temp - 1) << 2)] & 0x03) | (PD_Source[2 + ((temp - 1) << 2)] << 2);
        pd_tx_buf[2] = PD_Source[2 + ((temp - 1) << 2)];
        pd_tx_buf[1] = (0x10 | (MsgID << 1));
        pd_tx_buf[0] = 0x02 | (0xC0 & PD_Source[0]);
        pd_phy_tx_init();
    } else {
        my_printf("No Matched Volt.\n", 0);
    }
}
#else 

void pd_phy_send_req_capacity(void) {
    UINT16 Volt_Value;
    UINT8 sr_pdo_index = 0xff;  // 
    UINT8 i;
    UINT16 Temp;
    UINT16 curr_match_vol=0;
    _Union_SrcCap *match_src_cap=NULL;
    Request_SrcCap *req_cap=NULL;

    UINT8 o_cfg = get_out_cfg();

    if(o_cfg < USB_IN_CFG_MAX){
       Volt_Value = out_cfg_table[o_cfg];
    }else{
       Volt_Value = out_cfg_table[0]; 
    }
   
    for (i = 0; i < NDORcv; i++) {
        Union_SrcCap = (_Union_SrcCap *)&PD_Source[2 + (4 * i)];
        
        if (Union_SrcCap->fixed_pdo.pdo_type == AUGMENTED_POWER_DATA_OBJECT) {
            PPS_Flag = 1;
            my_printf("\r %d is PPS\n", (UINT16)(i + 1));
        } else {
            Temp = (UINT16)Union_SrcCap->fixed_pdo.VoltH<<8 | Union_SrcCap->fixed_pdo.VoltL;
            my_printf("usr-t:%d\n", Temp);

            Temp = (PD_Source[3 + (i << 2)] >> 2) + ((PD_Source[4 + (i << 2)] & 0x0F) << 6);
            my_printf("org-t:%d\n", Temp);

            // Temp *= 50;
            if (Temp <= Volt_Value) {
                if (Temp > curr_match_vol) {
                    curr_match_vol = Temp;
                    match_src_cap = Union_SrcCap;
                    sr_pdo_index = i + 1;
                }
            }
        }
    }

    if (sr_pdo_index != 0xff) {
        UPD_T_SOP = UPD_SOP0;
        UPD_T_LEN = 6;
        req_cap = (Request_SrcCap *)&pd_tx_buf[2];

        for(i=0;i<4;i++){
            req_cap->req_src_cap[i]=0;
        }

        req_cap->req_cap.max_op_curr_l = match_src_cap->fixed_pdo.CurrentL;
        req_cap->req_cap.max_op_curr_h = match_src_cap->fixed_pdo.CurrentH;

        Temp = match_src_cap->fixed_pdo.CurrentL|((UINT16)match_src_cap->fixed_pdo.CurrentH<<8);
        req_cap->req_cap.op_curr_l = Temp&0x3f;
        req_cap->req_cap.op_curr_h = (Temp>>8)&0x04;

        req_cap->req_cap.obj_possition = sr_pdo_index;

        pd_tx_buf[1] = (0x10 | (MsgID << 1));
        pd_tx_buf[0] = 0x02 | (0xC0 & PD_Source[0]);
        pd_phy_tx_init();
    } else {
        my_printf("No Matched Volt.\n", 0);
    }
}
#endif


void mTimer0_ISR(void) interrupt INT_NO_TMR0 {
    TR0 = 0;
    ET0 = 0;  //
    if (Send_Count < 3) {
        if (pd_phy_state.SendingRequest == 1) {
            pd_phy_send_req_capacity();
        }
        Send_Count++;
    } else {
        Send_Count = 0;
        pd_phy_state.SendingRequest = 0;
        pd_phy_rx_init();
    }
}

void usr_pd_port_isr(void) {
    if (MsgID > 7) {
        MsgID = 0;
    }

    if (pd_phy_state.SendingRequest == 1) {
        mTimer_x_SetData(2000);  // 1ms
    } else {
        pd_phy_rx_init();
    }
}


void pd_phy_h_reset(void) { UPD_CTRL |= bPD_RST_EN; }

void pd_phy_send_good_crc(void) {
    UPD_T_SOP = UPD_SOP0;
    UPD_T_LEN = 2;

    pd_tx_buf[1] = pd_rx_buf[1] & 0x0E;
    pd_tx_buf[0] = 0x41;

    pd_phy_tx_init();
}

void pd_phy_send_get_src_capacity_msg(void) {
    UPD_T_SOP = UPD_SOP0;
    UPD_T_LEN = 2;

    pd_tx_buf[1] = (0x00 | (MsgID << 1));
    pd_tx_buf[0] = 0x47;

    pd_phy_tx_init();
}

void pd_phy_send_sink_capacity_msg(void) {
    UPD_T_SOP = UPD_SOP0;
    UPD_T_LEN = 6;

    pd_tx_buf[5] = 0x32;
    pd_tx_buf[4] = 0x01;
    pd_tx_buf[3] = 0x91;
    pd_tx_buf[2] = 0x2C;

    pd_tx_buf[1] = ((((pd_rx_buf[1] ^ 0x01) & 0x01) | 0x10) | (MsgID << 1));
    pd_tx_buf[0] = 0x44;

    pd_phy_tx_init();
}


void pd_phy_rx_init(void) {
    UPD_INT_EN = bPIE_RX_ACT | bPIE_RX_RST;

    UPD_CTRL |= (bPD_CLR_ALL);
    UPD_CTRL &= ~(bPD_CLR_ALL | bPD_TX_EN);

    UPD_DMA_L = pd_rx_buf;
    UPD_TIMER = FREQ_SYS / 400000 - 1;

    PD_START = 1;
}

void pd_phy_tx_init(void) {
    PD_START = 0;
    UPD_INT_EN = bPIE_TX_END;

    UPD_CTRL |= (bPD_CLR_ALL | bPD_TX_EN);
    UPD_CTRL &= ~(bPD_CLR_ALL);

    UPD_DMA_L = pd_tx_buf;
    UPD_TIMER = FREQ_SYS / 600000 - 1;

    if (CCSel == 1) {
        CC1_CTRL |= bCC_LVO;  
    } else if (CCSel == 2) {
        CC2_CTRL |= bCC_LVO;
    }
    PD_START = 1;
}
